
package org.sidora.core;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;
import org.sidora.core.context.Context;
import org.sidora.core.util.AbstractFactory;
import org.sidora.core.util.AbstractInventory;
import org.sidora.core.util.OCProvider;
import org.sidora.core.util.ParameterCollector;



/**
 * Zone
 * @author Enric Tartera, Anna Arnalot, Juan Manuel Gimeno, Roger Masgoret
 * @version 1.0
 */
public class Zone implements Comparable {
    
    private KeyObject idZone = new KeyObject();
    
    //private TreeSet<Sector> sectors = new TreeSet <Sector>();
    //private TreeSet<Context> contexts = new TreeSet <Context>();
    //private TreeSet<Feature> features = new TreeSet <Feature>();
    
    private String description;
    //private DiagramaZona dgz;
    
    
    private Zone(){
    }
    
    public TreeSet<Context> getContexts() {
        return new TreeSet<Context>(Context.Inventory.getList(this));
    }
    
    public TreeSet<Feature> getFeatures() {
        return new TreeSet<Feature>(Feature.Inventory.getList(this));
    }
    
    public TreeSet<Sector> getSectors() {
        return new TreeSet<Sector>(Sector.Inventory.getList(this));
    }
    
//	public DiagramaZona getDgz() {
//		return dgz;
//	}
//
//	public void setDgz(DiagramaZona dgz) {
//		this.dgz = dgz;
//	}
    
    /**
     * @return Returns the contexts.
     */
    public List<Context> getDBContexts() {
        Zone zone = this;
        return Context.Inventory.getList(zone);
    }
    
    
    /**
     * @return Returns the idZona.
     */
    public KeyObject getIdZone() {
        return idZone;
    }
    /**
     * @param idZona The idZona to set.
     */
    public void setIdZone(KeyObject idZone) {
        this.idZone = idZone;
    }
    
    /**
     * @return Returns the sectors.
     */
    public List <Sector> getDBSectors() {
        Zone zone =this;
        return Sector.Inventory.getList(zone);
    }
    /**
     * @param sectors The sectors to set.
     */
    
    /**
     * @return Returns the site.
     */
    public Site getSite() {
        return idZone.getSite();
    }
    /**
     * @param site The site to set.
     */
    public List<Feature> getDBFeatures() {
        Zone zone = this;
        return Feature.Inventory.getList(zone);
    }
    
    
    
    public void setSite(Site site) {
        this.idZone.setSite(site);
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    
    public boolean equals(Object obj) {
        if (obj == this)	return true;
        if (!(obj instanceof Zone)) return false;
        Zone zone = null;
        try {
            zone = (Zone) obj;
        } catch (Exception e) {
            return false;
        }
        if (!this.idZone.equals(zone.idZone)) return false;
        return true;
    }
    
    public int compareTo(Object obj) {
        Zone azone = (Zone) obj;
        return this.idZone.compareTo(azone.idZone);
    }
    
    @Override
    public String toString() {
        StringBuilder stringbuilder = new StringBuilder();
        stringbuilder.append("Zona: "+idZone);
        if (idZone.getSite().getAcronym()!= null)
                stringbuilder.append(" ("+idZone.getSite().getAcronym()+")");
        return stringbuilder.toString();
    }
    
    
//private static class Factory extends AbstractFactory{
//
//    	protected Object create(ParameterCollector param) {
//    		// La pol�tica de creaci� de zones determina que nom�s un usuari
//    		//amb rol "admin" pot crear noves zones.
//    		// Per defecte es permet tamb? el password de root declarat com a variable est�tica de User
//
//
//    				return new Zone();
//
//
//    	}
//    }
    public static class Inventory extends AbstractInventory{
        
        public static boolean exist(final KeyObject id) throws Exception{
            
            ObjectContainer db = OCProvider.getInstance();
            ObjectSet<Zone> zones = db.query(new Predicate<Zone>() {
                
                
                public boolean match(Zone candidate) {
                    return candidate.idZone.equals(id);
                }
            });
            db.commit();
            if (zones.hasNext()){
                return true;
            } else {
                return false;
            }
        }
        
        public Zone getNewObject(ParameterCollector param) throws Exception{
            // Delega en la factoria corresponent la creaci� d'una nova intervenció en
            // el cas que aquesta no existeixi
            //Obt? la clau i el site al que pertany
            KeyObject newId= this.getNewKey(param);
            //Delega en la factoria la creació
            //param.put("factoryid", "Zone");
            Zone zone = new Zone();//(Zone) Zone.Factory.createObject(param);
            zone.setIdZone(newId);
            
            return zone;
        }
        
        
        public static Zone getZone(String context, Site site) throws Exception {
            String nzone;
            
            try{
                nzone = (String) context.trim().subSequence(0, context.length()-3);
            }catch (Exception e) {
                throw(new Exception("Zone not found"));
            }
            
            final Integer integ = new Integer(nzone);
            Zone zone =null;
            
            //Set zoneset = site.getZones();
            List zonelist = Zone.Inventory.getList();
            int quant = zonelist.size();
            
            List zoneset = Zone.Inventory.getList(site);
            int quant2= zoneset.size();
            
            Iterator iter = zoneset.iterator();
            
            while (iter.hasNext()){
                Zone azone = (Zone) iter.next();
                if (azone.getIdZone().getNumber().equals(integ)){
                    zone =azone;
                    break;
                }
            }
            
            return zone;
        }
        
        protected KeyObject getNewKey(ParameterCollector param)  {
            
            //	Cal passar com a par�metres el jaciment del qual forma part la zona
            
            final Site site = (Site) param.get("site");
            //S'instancia una nova clau
            KeyObject key = new KeyObject();
            //se li dona el valor inicial per defecte
            key.setNumber(0);
            key.setSite(site);
            //es busca a la base d'objectes totes les inst�ncies de Zona del jaciment indicat
            ObjectContainer db = OCProvider.getInstance();
            List zones = Zone.Inventory.getList(site);
            //En cas que hi hagi d'altres zones al jaciment, busca el m�s alt i en suma un
            
            if (zones.size()!= 0){
                TreeSet <Zone> tree = new TreeSet<Zone>(zones);
                Zone zone = tree.last();
                Integer integer = zone.idZone.getNumber()+1;
                key.setNumber(integer);
                return key;
            }
            //En cas contrari pasa el valor per defecte
            
            else return key;
            
            
        }
        
        
        public Object getObject(ParameterCollector param) {
            //Carrega el Site amb el corresponent siteid
            final String key = (String) param.get("id");
            ObjectContainer db = OCProvider.getInstance();
            
            ObjectSet <Zone> zones = db.query(new Predicate <Zone>() {
                public boolean match(Zone azone) {
                    return (azone.getIdZone().equals(key));
                }
            });
            db.commit();
            
            if (zones.hasNext()){
                return zones.next();
            } else throw new RuntimeException("Zona inexistent");
        }
        public static Zone getZone(final KeyObject key) {
            //Obt? una zona a partr del seu key
            
            ObjectContainer db = OCProvider.getInstance();
            
            ObjectSet <Zone> zones = db.query(new Predicate <Zone>() {
                public boolean match(Zone azone) {
                    return (azone.getIdZone().equals(key));
                }
            });
            db.commit();
            return null;
        }
        
        public static List getList() {
            
            ObjectContainer db = OCProvider.getInstance();
            List<Zone> list = db.query(Zone.class);
            db.commit();
            return list;
            
        }
        
        public static List getList(final Site site) {
            
            ObjectContainer db = OCProvider.getInstance();
            List<Zone> list = db.query(new Predicate<Zone>(){
                
                @Override
                public boolean match(Zone zone) {
                    // TODO Auto-generated method stub
                    return zone.idZone.getSite()==site;
                }});
                
                db.commit();
                return list;
                
        }
    }
    
} // end Zona



